package com.fengye.algorithms.alibaba.dagscheduler;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * 任务调度，基于有向无环图
 * @Author fengye
 * @Date 2023/4/6 11:52
 **/
public class Scheduler {
    public void schedule(TaskDigraph digraph) {
        while (true) {
            List<Task> todos = new ArrayList<>();
            for (Task task : digraph.getTasks()) {
                if (!task.hasEexecuted()) {
                    Set<Task> prevs = digraph.getEdges().get(task);
                    if (prevs != null && !prevs.isEmpty()) {
                        boolean toAdd = true;
                        for (Task prevTask : prevs) {
                            // 如果当前task的前置任务有一个没有执行，则不将当前任务加入本次执行任务中
                            if (!prevTask.hasEexecuted()) {
                                toAdd = false;
                                break;
                            }
                        }
                        // 将当前任务的前置任务都执行过了加入执行任务中
                        if (toAdd) {
                            todos.add(task);
                        }
                    }else {
                        // 没有前置任务的任务加入任务中
                        todos.add(task);
                    }
                }
            }

            if (!todos.isEmpty()) {
                for (Task task : todos) {
                    task.execute();
                }
            } else {
                break;
            }
        }
    }

    public static void main(String[] args) {
        TaskDigraph digraph = new TaskDigraph();
        Task task1 = new Task(1L, "task1", 0);
        Task task2 = new Task(2L, "task2", 0);
        Task task3 = new Task(3L, "task3", 0);
        Task task4 = new Task(4L, "task4", 0);
        Task task5 = new Task(5L, "task5", 0);
        Task task6 = new Task(6L, "task6", 0);
        digraph.addTask(task1);
        digraph.addTask(task2);
        digraph.addTask(task3);
        digraph.addTask(task4);
        digraph.addTask(task5);
        digraph.addTask(task6);
        digraph.addEdge(task1, task2);
        digraph.addEdge(task1, task5);
        digraph.addEdge(task6, task2);
        digraph.addEdge(task2, task3);
        digraph.addEdge(task2, task4);
        Scheduler scheduler = new Scheduler();
        scheduler.schedule(digraph);
    }
}
